package l.l.w.UnderstandingJVM.proxy;

import l.Proxy11;
import org.junit.Test;
import sun.misc.ProxyGenerator;

import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.*;
import java.net.URL;
import java.net.URLClassLoader;

/**
 * Created by llw on 2018/5/10/0010.
 */
public class TestProxy {

    @Test
    public void demo3() throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        Class<?> clazz = Class.forName("l.User");
        Constructor<?> constructor = clazz.getConstructor(String.class, Integer.class);
        Object o = constructor.newInstance("zhangsan", 10);
        System.out.println(o);
    }



    @Test
    public void demo2() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {


        Class<?> clazz = Class.forName("l.Proxy11");
        InvocationHandler handler = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                return null;
            }
        };
        Proxy11 proxy11 = new Proxy11(handler);
//        Proxy11 proxy11 = new Proxy11();
//        l.l.w.UnderstandingJVM.proxy.Proxy11 $proxy = new l.l.w.UnderstandingJVM.proxy.Proxy11(handler);
        Constructor<?> constructor = clazz.getConstructor(InvocationHandler.class);
        UserDao userDao = (UserDao) constructor.newInstance(handler);
        userDao.insert(1);
    }


    @Test
    public void demo4(){
        System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
        UserDao userDao = new UserDaoImpl();
        UserDao userDaoProxy1 = (UserDao)Proxy.newProxyInstance(userDao.getClass().getClassLoader(), userDao.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("before1");
                Object invoke = method.invoke(userDao, args);
                System.out.println("after1");
                return invoke;
            }
        });
        userDaoProxy1.insert(10);
    }


    @Test
    public void demo1(){
        UserDao userDao = new UserDaoImpl();
        UserDao userDaoProxy1 = (UserDao)Proxy.newProxyInstance(userDao.getClass().getClassLoader(), userDao.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("before1");
                Object invoke = method.invoke(userDao, args);
                System.out.println("after1");
                return invoke;
            }
        });

        userDaoProxy1.insert(10);


        UserDao userDaoProxy2 = (UserDao)Proxy.newProxyInstance(userDao.getClass().getClassLoader(), userDao.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("before2");
                Object invoke = method.invoke(userDao, args);
                System.out.println("after2");
                return invoke;
            }
        });
        userDaoProxy2.insert(10);
        System.out.println(userDaoProxy1.equals(userDaoProxy2));
        System.out.println(userDaoProxy1.getClass() == userDaoProxy2.getClass());
        System.out.println(userDaoProxy1.getClass() == userDao.getClass());

        ActDao actDao = new ActDaoImpl();
        ActDao actDaoProxy = (ActDao)Proxy.newProxyInstance(this.getClass().getClassLoader(), actDao.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                return method.invoke(actDao, args);
            }
        });

        actDao.insert(10);

        System.out.println(actDaoProxy.getClass());
        System.out.println(userDaoProxy1.getClass());
        System.out.println(userDaoProxy2.getClass());
        System.out.println(actDaoProxy.getClass() == userDaoProxy1.getClass());

//        byte[] bytes = ProxyGenerator.generateProxyClass("l.Proxy11", userDao.getClass().getInterfaces());
        byte[] bytes = ProxyGenerator.generateProxyClass("l.Proxy11",userDao.getClass().getInterfaces());
        FileOutputStream out = null;

        try {
            out = new FileOutputStream("myLib/l/Proxy11.class");
            out.write(bytes);
            out.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
